/*
 *  dna_hexbin.c -- provide dna-system Hex and Bin convert interface.
 *  
 *  ORIGINAL AUTHOR: Xu Chun (chun.xu@broadlink.com.cn)
 *
 *  Copyright (c) 2016 Broadlink Corporation
 */

#include "dna_libc.h"

static int simp_toupper(int c)
{
   if (c >='a' && c <= 'z')
      c = c - ('a' - 'A');
   
   return c;
}

unsigned int dna_hex2bin(const unsigned char * ibuf, unsigned char * obuf,
		        unsigned max_olen)
{
	unsigned int i;		/* loop iteration variable */
	unsigned int j = 0;	/* current character */
	unsigned int by = 0;	/* byte value for conversion */
	unsigned char ch;	/* current character */
	unsigned int len = dna_strlen((char *)ibuf);
	/* process the list of characters */
	for (i = 0; i < len; i++) {
		if (i == (2 * max_olen)) {
			dna_printf("hexbin: %s", "Destination full. "
				"Truncating to avoid overflow.\r\n");
			return j + 1;
		}
		ch = simp_toupper(*ibuf++);	/* get next uppercase character */

		/* do the conversion */
		if (ch >= '0' && ch <= '9')
			by = (by << 4) + ch - '0';
		else if (ch >= 'A' && ch <= 'F')
			by = (by << 4) + ch - 'A' + 10;
		else {		/* error if not hexadecimal */
			return 0;
		}

		/* store a byte for each pair of hexadecimal digits */
		if (i & 1) {
			j = ((i + 1) / 2) - 1;
			obuf[j] = by & 0xff;
		}
	}
	return j + 1;
}

int dna_bin2hex(const unsigned char * src, char * dest, unsigned int src_len,
	     unsigned int dest_len)
{
	int i;
    char * start = dest;

    dna_memset(dest, 0, dest_len);
    
	for (i = 0; i < src_len; i++) {
		if (dna_snprintf(dest, dest_len, "%02x", src[i]) >= dest_len) {
			dna_printf("hexbin: %s", "Destination full. "
				"Truncating to avoid overflow.\r\n");
            dest += 2;
			break;
		}
		dest_len -= 2;
		dest += 2;
	}

    return (dest - start);
}

void dna_hexdump(const void *data, size_t size, const char *str, ...)
{
    char t_str[128];
    char hexByte[4];
    char hexLine[50];
    char charByte[2];
    char charLine[18];

    va_list args;
    va_start(args, str);
    int len = dna_vsnprintf(t_str, sizeof(t_str), str, args);
    va_end(args);
    dna_printf("%.*s\r\n", len, t_str);

    unsigned int i;
    for (i = 0; i < size; i++) {
        if (i % 16 == 0) {
            hexLine[0] = 0;
            charLine[0] = 0;
        }
        if (i % 16 == 8) {
            dna_strcat(hexLine, " ");
            dna_strcat(charLine, " ");
        }
        dna_snprintf(hexByte, sizeof(hexByte), " %02x", ((unsigned char *) data)[i]);
        dna_strcat(hexLine, hexByte);
        if (((unsigned char *) data)[i] < 32 || ((unsigned char *) data)[i] > 126) {
            dna_strcat(charLine, ".");
        } else {
            dna_snprintf(charByte, sizeof(charByte), "%c", ((unsigned char *) data)[i]);
            dna_strcat(charLine, charByte);
        }
        if (i % 16 == 15 || i == size - 1) {
            dna_printf("%04x:%-49s  %s\r\n", i & ~15, hexLine, charLine);
        }
    }
}
